package top.wilbert.collegelink.search.service.impl;/**
 * @author augus
 * @create 2023-03-17-21:37
 */

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.wilbert.collegelink.common.enums.TargetTypeEnum;
import top.wilbert.collegelink.common.vo.es.TalkEsModel;
import top.wilbert.collegelink.search.config.CollegelinkElasticSearchConfig;
import top.wilbert.collegelink.search.constant.EsConstant;
import top.wilbert.collegelink.search.feign.ForumFeignService;
import top.wilbert.collegelink.search.service.ForumSearchService;
import top.wilbert.collegelink.search.vo.TalkSearchParam;
import top.wilbert.collegelink.search.vo.TalkSearchResult;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Augus
 * @ClassName:ForumSearchServiceImpl
 * @Description:
 * @date 2023/3/17 21:37
 * @Version 1.0
 **/
@Slf4j
@Service("forumSearchService")
public class ForumSearchServiceImpl implements ForumSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ForumFeignService forumFeignService;

    @Override
    public TalkSearchResult searchTalk(TalkSearchParam talkSearchParam) {
        //动态构建出查询需要的DSL语句
        TalkSearchResult talkSearchResult = null;

        //1、准备检索请求
        SearchRequest searchRequest = buildSearchRequest(talkSearchParam);

        try {
            //2、执行检索请求
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, CollegelinkElasticSearchConfig.COMMON_OPTIONS);
            //3、分析响应数据封装成我们需要的格式
            talkSearchResult = buildSearchResult(searchResponse, talkSearchParam);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return talkSearchResult;
    }

    /**
     * 准备检索请求
     * @param param
     * @return
     */
    private SearchRequest buildSearchRequest(TalkSearchParam param) {

        //用来构建DSL语句
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //1、构建bool - query
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //1.1、must-模糊匹配
        if (!StringUtils.isEmpty(param.getKeyword())) {
            BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery();
            shouldQuery.should(QueryBuilders.matchQuery("title", param.getKeyword()));
            shouldQuery.should(QueryBuilders.matchQuery("content", param.getKeyword()));
            shouldQuery.minimumShouldMatch(1);
            boolQuery.must(shouldQuery);
        }

        //1.2、bool-filter
        //1.2.1、按照标签查询
        if (param.getTag() != null) {
            boolQuery.filter(QueryBuilders.termQuery("tag", param.getTag()));
        }

        //1.2.2、按照话题分类查询
        if (param.getType() != null) {
            boolQuery.filter(QueryBuilders.termQuery("type", param.getType()));
        }

        //1.2.2、按照话题分类查询
        if (param.getSchoolId() != null) {
            boolQuery.filter(QueryBuilders.termQuery("schoolId", param.getSchoolId()));
        }

        //封装所有的查询条件
        searchSourceBuilder.query(boolQuery);

        //排序
        String orderFiled = "";
        if (!StringUtils.isEmpty(param.getOrderFiled())) {
            orderFiled = param.getOrderFiled();
        } else {
            orderFiled = "createTime";
        }

        String order = "";
        if (!StringUtils.isEmpty(param.getOrder())) {
            order = param.getOrder();
        } else {
            order = "desc";
        }

        SortOrder sortOrder = "asc".equalsIgnoreCase(order) ? SortOrder.ASC : SortOrder.DESC;
        searchSourceBuilder.sort(orderFiled, sortOrder);

        //分页
        searchSourceBuilder.from((param.getCurrPage() - 1) * EsConstant.TALK_PAGESIZE);
        searchSourceBuilder.size(EsConstant.TALK_PAGESIZE);

        log.debug("构建的DSL语句 {}", searchSourceBuilder.toString());

        SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.TALK_INDEX}, searchSourceBuilder);

        return searchRequest;
    }

    /**
     * 构建结果数据
     * 模糊匹配，完成排序、分页功能
     * @param response
     * @param param
     * @return
     */
    private TalkSearchResult buildSearchResult(SearchResponse response, TalkSearchParam param) {

        TalkSearchResult result = new TalkSearchResult();

        //1、返回的所有查询到的商品
        SearchHits hits = response.getHits();

        List<TalkEsModel> esModels = new ArrayList<>();
        //遍历所有话题信息
        if (hits.getHits() != null && hits.getHits().length > 0) {
            for (SearchHit hit : hits.getHits()) {
                String sourceAsString = hit.getSourceAsString();
                TalkEsModel esModel = JSON.parseObject(sourceAsString, TalkEsModel.class);
                Boolean isLike = forumFeignService.isLike(esModel.getTalkId(), TargetTypeEnum.TALK.getTargetType(), param.getUserId());
                esModel.setIsLike(isLike);
                esModels.add(esModel);
            }
        }
        result.setTalks(esModels);

        //2、分页信息
        result.setCurrPage(param.getCurrPage());
        result.setPageSize(EsConstant.TALK_PAGESIZE);
        int totalCount =(int)hits.getTotalHits().value;
        result.setTotalCount(totalCount);
        int totalPage = totalCount % EsConstant.TALK_PAGESIZE == 0 ? totalCount / EsConstant.TALK_PAGESIZE : (totalCount / EsConstant.TALK_PAGESIZE + 1);
        result.setTotalPage(totalPage);

        return result;
    }

}
